//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
//==========================================================================
// Copyright (c) 2000-2004,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>
#include "rtl4if.h"

//
// Rtl4If
//

class Rtl4If : public CDeviceDriver
{
public:
    CARAPI Read(
        /* [in] */ UInt64 u64Offset,
        /* [in] */ UInt32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ UInt64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ UInt32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf & inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    virtual void Dispose();

public:

private:
    void* m_rtl8139;
};

ECode Rtl4If::Read(
    /* [in] */ UInt64 u64Offset,
    /* [in] */ UInt32 bytesToRead,
    /* [out] */ MemoryBuf * pBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    unsigned int uStatus;
    netdrv * pThis = (netdrv*)bytesToRead;
    WaitResult wr;
    if (pBuffer == NULL) {
        return E_INVALID_ARGUMENT;
    }
    pThis->pRWevent->Wait(&wr, &uStatus);
    pBuffer->Copy((Byte *)&uStatus, sizeof(unsigned int));
    return NOERROR;
}

ECode Rtl4If::Write(
    /* [in] */ UInt64 u64Offset,
    /* [in] */ const MemoryBuf & buffer,
    /* [out] */ UInt32 * pBytesWritten,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    rtl_8139xmit((netdrv*)buffer.GetPayload());
    return NOERROR;
}

ECode Rtl4If::Control(
    /* [in] */ Handle32 nControlCode,
    /* [in] */ const MemoryBuf & inBuffer,
    /* [out] */ MemoryBuf * pOutBuffer,
    /* [out] */ IEvent ** ppCompletionEvent)
{
    if (nControlCode == DRVINITALIZE) {
        if (pOutBuffer == NULL) {
            return E_INVALID_ARGUMENT;
        }
        rtl_8139_connect((void*)inBuffer.GetPayload(),
                        (void**)pOutBuffer->GetPayload());
    }
    else if (nControlCode == ENABLEIRQ) {
        _EnableIrq();
    }
    else if (nControlCode == DISABLEIRQ) {
        _DisableIrq();
    }
    else if (nControlCode == DRVSHUTDOWN) {
        rtl_8139_stutdown((netdrv*)inBuffer.GetPayload());
    }
    else {
        kprintf("unknown ControlCode\n");
    }
    return NOERROR;
}

void Rtl4If::Dispose()
{
    delete this;
}

void getdriverinfo(int * pirq, int * piobase);
EXTERN IDeviceDriver * CDECL CreateRtl4Usnet(uint_t uDeviceNo,
                void *pvParameter)
{
    IDeviceDriver *pDriver;
    int irq, iobase;

    getdriverinfo(&irq, &iobase);
    pDriver = new Rtl4If();
    if (NULL == pDriver) return NULL;
    pDriver->AddRef();
    rtl_8139new(&iobase, &irq, NULL);
    return pDriver;
}
